<?php

namespace App\Services;

use App\Models\Post;
use App\Models\Reply;
use App\Models\ReplyLike;
use App\Models\User;
use App\Notifications\PostReplied;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\DB;

class ReplyService
{
    /**
     * 创建回复（支持楼中楼）
     */
    public function createReply(Post $post, User $user, array $data): Reply
    {
        return DB::transaction(function () use ($post, $user, $data) {
            // 创建回复
            $reply = Reply::create([
                'user_id' => $user->id,
                'post_id' => $post->id,
                'parent_id' => $data['parent_id'] ?? null, // 楼中楼回复
                'content' => $data['content'],
                'like_count' => 0,
            ]);

            // 更新帖子回复数（只统计主回复，不包括楼中楼）
            if (! $reply->parent_id) {
                $post->increment('reply_count');
            }

            // 增加用户经验值（回复奖励）
            $user->increment('exp', 2);

            // 加载关联关系
            $reply->load(['user', 'parent.user', 'post.bar']);

            // 发送通知
            // 1. 通知帖子作者（如果回复者不是作者本人）
            if ($post->user_id !== $user->id) {
                $post->user->notify(new PostReplied($reply, $user));
            }

            // 2. 如果是楼中楼回复，通知被回复的回复作者（如果回复者不是被回复者本人）
            if ($reply->parent_id && $reply->parent->user_id !== $user->id) {
                $reply->parent->user->notify(new PostReplied($reply, $user));
            }

            return $reply;
        });
    }

    /**
     * 获取帖子的回复列表（支持嵌套结构）
     *
     * @param  Post  $post  帖子
     * @param  User|null  $user  当前用户（用于标记点赞状态）
     * @param  int  $perPage  每页数量
     */
    public function getRepliesList(Post $post, ?User $user = null, int $perPage = 20): LengthAwarePaginator
    {
        // 获取主回复（不包括楼中楼）
        // 递归加载所有层级的子回复（最多3层，避免过深）
        $query = $post->replies()
            ->with([
                'user',
                'children.user', // 第一层
                'children.parent.user', // 第一层的父回复用户（用于显示"回复了谁"）
                'children.children.user', // 第二层
                'children.children.parent.user', // 第二层的父回复用户
                'children.children.children.user', // 第三层
                'children.children.children.parent.user', // 第三层的父回复用户
            ]);

        // 优化：如果用户已登录，批量预加载用户的点赞关系，避免N+1查询
        if ($user) {
            $query->with([
                'likes' => function ($q) use ($user) {
                    $q->where('user_id', $user->id);
                },
                'children.likes' => function ($q) use ($user) {
                    $q->where('user_id', $user->id);
                },
                'children.children.likes' => function ($q) use ($user) {
                    $q->where('user_id', $user->id);
                },
                'children.children.children.likes' => function ($q) use ($user) {
                    $q->where('user_id', $user->id);
                },
            ]);
        } else {
            // 未登录用户也需要加载likes关系（用于显示点赞数），但不筛选
            $query->with([
                'children.likes',
                'children.children.likes',
                'children.children.children.likes',
            ]);
        }

        $replies = $query->withCount('children') // 楼中楼数量
            ->paginate($perPage);

        // 批量标记点赞状态（基于预加载的关系）
        if ($user) {
            $replies->getCollection()->transform(function ($reply) {
                $this->markReplyLikeStatusOptimized($reply);

                return $reply;
            });
        }

        return $replies;
    }

    /**
     * 递归标记回复的点赞状态（优化版：使用预加载的关系）
     *
     * 此方法使用预加载的 likes 关系来判断是否点赞，避免 N+1 查询问题。
     * 处理完点赞状态后，会清理预加载的关系以减少内存占用。
     *
     * @param  \App\Models\Reply  $reply  回复模型实例
     */
    private function markReplyLikeStatusOptimized($reply): void
    {
        // 使用预加载的关系判断是否点赞，避免额外的数据库查询
        $reply->is_liked = $reply->likes->isNotEmpty();
        // 清理预加载的关系，避免数据冗余
        unset($reply->likes);

        // 递归处理子回复
        if ($reply->children && $reply->children->count() > 0) {
            foreach ($reply->children as $child) {
                $this->markReplyLikeStatusOptimized($child);
            }
        }
    }

    /**
     * 点赞/取消点赞回复
     */
    public function toggleLike(Reply $reply, User $user): bool
    {
        return DB::transaction(function () use ($reply, $user) {
            $like = ReplyLike::where('reply_id', $reply->id)
                ->where('user_id', $user->id)
                ->first();

            if ($like) {
                // 取消点赞
                $like->delete();
                $reply->decrement('like_count');

                return false; // 已取消点赞
            } else {
                // 点赞
                ReplyLike::create([
                    'reply_id' => $reply->id,
                    'user_id' => $user->id,
                ]);
                $reply->increment('like_count');

                // 增加回复作者经验值（被点赞奖励）
                $reply->user->increment('exp', 1);

                return true; // 已点赞
            }
        });
    }

    /**
     * 更新回复
     */
    public function updateReply(Reply $reply, User $user, array $data): Reply
    {
        return DB::transaction(function () use ($reply, $user, $data) {
            // 检查权限：只有作者可以更新
            if (! $reply->isAuthor($user)) {
                throw new \Illuminate\Auth\Access\AuthorizationException('您无权更新此回复');
            }

            $reply->update([
                'content' => $data['content'],
            ]);

            return $reply->fresh();
        });
    }

    /**
     * 删除回复
     */
    public function deleteReply(Reply $reply, User $user): bool
    {
        return DB::transaction(function () use ($reply, $user) {
            // 检查权限：作者、帖子作者、吧主或管理员可以删除
            if (! $reply->isAuthor($user) && ! $reply->post->isAuthor($user) && ! $reply->post->bar->isOwner($user) && ! $user->isAdmin()) {
                throw new \Illuminate\Auth\Access\AuthorizationException('您无权删除此回复');
            }

            // 如果是主回复，需要减少帖子回复数
            if (! $reply->parent_id) {
                $reply->post->decrement('reply_count');
            }

            // 级联删除子回复（数据库外键已设置 cascade）
            $deleted = $reply->delete();

            return $deleted;
        });
    }
}
